package com.yiyuan.app.mqtt;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.mqtt.server.callback.MessageListener;
import com.alibaba.mqtt.server.model.MessageProperties;
import com.guaike.core.redis.annotation.TryLock;
import com.guaike.core.redis.enums.LockModel;
import com.yiyuan.app.dao.GConfDeviceDAO;
import com.yiyuan.app.dao.GConfRoomDeviceDAO;
import com.yiyuan.app.dao.GRecordGameDAO;
import com.yiyuan.app.dao.GRecordMqttMessageDAO;
import com.yiyuan.app.entity.constant.MQTTTopicConstant;
import com.yiyuan.app.entity.enums.MessageTypeEnum;
import com.yiyuan.app.entity.enums.RoomTypeEnum;
import com.yiyuan.app.entity.po.GConfDevicePO;
import com.yiyuan.app.entity.po.GConfRoomDevicePO;
import com.yiyuan.app.entity.po.GRecordGamePO;
import com.yiyuan.app.entity.po.GRecordMqttMessagePO;
import com.yiyuan.app.service.MQTTService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Objects;

@Slf4j
@Component
@AllArgsConstructor
public class MachineSettleListener implements MessageListener {
    private final MQTTService mqttService;
    private final GRecordMqttMessageDAO gRecordMqttMessageDAO;
    private final GRecordGameDAO gRecordGameDAO;
    private final GConfDeviceDAO gConfDeviceDAO;
    private final GConfRoomDeviceDAO gConfRoomDeviceDAO;

    @SneakyThrows
    @Override
    @TryLock(lockKey = "#msgId", lockModel = LockModel.REENTRANT)
    public void process(String msgId, MessageProperties messageProperties, byte[] payload) {
        try {
            String msg = new String(payload, StandardCharsets.UTF_8);
            log.info("Receive message : msgId = {}, messageProperties = {}, payload = {}", msgId, JSONObject.toJSONString(messageProperties), msg);
            String[] split = messageProperties.getSecondTopic().split(MQTTTopicConstant.SEPARATOR_KEY);
            if (!"settle".equals(split[1])) {
                return;
            }
            String[] s = msg.split("_");
            String deviceNo = s[0];
            String command = s[1];
            GConfDevicePO devicePO = gConfDeviceDAO.findOne(GConfDevicePO::getSerialNumber, deviceNo);
            if (Objects.isNull(devicePO)) {
                return;
            }
            if (!(devicePO.getDeviceType().equals(RoomTypeEnum.arcade_machine.getCode()) || devicePO.getDeviceType().equals(RoomTypeEnum.recreation.getCode()))) {
                return;
            }
            GConfRoomDevicePO roomDevicePO = gConfRoomDeviceDAO.findOne(GConfRoomDevicePO::getDeviceId, devicePO.getId());
            if (Objects.isNull(roomDevicePO)) {
                return;
            }
            GRecordGamePO gamePO = gRecordGameDAO.findRoomPlaying(roomDevicePO.getRoomId(), roomDevicePO.getPositionNo());
            if (Objects.isNull(gamePO)) {
                return;
            }
            GRecordMqttMessagePO messagePO = new GRecordMqttMessagePO();
            messagePO.setMessageId(msgId);
            messagePO.setParentTopic(messageProperties.getFirstTopic());
            messagePO.setChildTopic(messageProperties.getSecondTopic());
            messagePO.setMessage(command);
            messagePO.setStatus(Boolean.FALSE);
            messagePO.setCommandCode(command);
            messagePO.setSerialNumber(deviceNo);
            messagePO.setMessageType(MessageTypeEnum.game.getCode());
            messagePO.setGameId(gamePO.getId());
            gRecordMqttMessageDAO.save(messagePO);
            mqttService.dealMachineSettle(messagePO);
        } catch (Exception e) {
            if (e.getMessage().contains("Duplicate entry")) {
                return;
            }
            log.error("MachineSettleListener error={}", e);
            throw new Exception(e);
        }
    }
}
